home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 March / EnigmA AMIGA RUN 05 (1996)(G.R. Edizioni)(IT)[!][issue 1996-03][Skylink CD IV].iso / earcd / program / ixemlsrc.lha / ixemul / library / convert_dir.c < prev    next >
C/C++ Source or Header  |  1995-12-23  |  6KB  |  197 lines

  1. /*
  2.  *  This file is part of ixemul.library for the Amiga.
  3.  *  Copyright (C) 1991, 1992  Markus M. Wild
  4.  *  Portions Copyright (C) 1994 Rafael W. Luebbert
  5.  *
  6.  *  This library is free software; you can redistribute it and/or
  7.  *  modify it under the terms of the GNU Library General Public
  8.  *  License as published by the Free Software Foundation; either
  9.  *  version 2 of the License, or (at your option) any later version.
  10.  *
  11.  *  This library is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.  *  Library General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU Library General Public
  17.  *  License along with this library; if not, write to the Free
  18.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  *
  20.  *  $Id: convert_dir.c,v 1.4 1994/06/19 15:09:22 rluebbert Exp $
  21.  *
  22.  *  $Log: convert_dir.c,v $
  23.  *  Revision 1.4  1994/06/19  15:09:22  rluebbert
  24.  *  *** empty log message ***
  25.  *
  26.  *  Revision 1.2  1992/07/28  00:42:36  mwild
  27.  *  fix signals, fix memory leak, fix possible never unlocked lock
  28.  *
  29.  *  Revision 1.1  1992/05/14  19:55:40  mwild
  30.  *  Initial revision
  31.  *
  32.  */
  33.  
  34. #define KERNEL
  35. #include "ixemul.h"
  36. #include "kprintf.h"
  37. #include <string.h>
  38.  
  39. /* don't need to use the async port, no more than 1 task will be in here
  40.  * at a time and use our packet */
  41. #define __srwport (u.u_sync_mp)
  42.  
  43. extern int __mread (), __mclose ();
  44.  
  45. #define BUFINCR    512
  46.  
  47. /* we're writing records that look like this to the `file' */
  48. struct file_dir {
  49.   long    fd_key;
  50.   long    fd_namelen;    /* padded to even size, thus perhaps zero padded */
  51.   char    fd_name[0];    /* fd_namelen bytes of filename */
  52. };
  53.  
  54. /*
  55.  * Convert a directory into a DTYPE_MEM file.
  56.  *
  57.  * NOTE: function assumes:
  58.  *     o f is allocated and locked, it's packet is initialized
  59.  *       o name is an existing directory (S_IFDIR from a previous stat)
  60.  *     o signals are blocked (important! convert_dir() doesn't block them!)
  61.  */
  62.  
  63. int
  64. convert_dir (struct file *f, char *name, int omask)
  65. {
  66.   BPTR lock;
  67.   u_char *buf, *bp, *bend;
  68.   int  buf_size;
  69.   struct FileInfoBlock *fib;
  70.   struct file_dir *fd;
  71.   int len, res, err = 0, rc0;
  72.  
  73.   fib = alloca (sizeof (*fib) + 2);
  74.   fib = LONG_ALIGN (fib);
  75.   
  76.   res = 0;
  77.   if ((lock = __lock (name, ACCESS_READ)) > 0)
  78.     {
  79.       buf = kmalloc (BUFINCR);
  80.       buf_size = BUFINCR;
  81.       bp = buf;
  82.       bend = buf + buf_size;
  83.  
  84.       /* make sure we got that memory */
  85.       if (! buf)
  86.         {
  87.           err = ENOMEM;
  88.           res = -1;
  89.           goto do_return;
  90.         }
  91.       
  92.       rc0 = Examine (lock, fib);
  93.  
  94.       /* put two dummy entries here.. some BSD code relies on the fact that
  95.        * it can safely skip the first two `.' and `..' entries ;-)) */
  96.       fd = (struct file_dir *) bp;
  97.       fd->fd_key = 1;
  98.       fd->fd_namelen = 2;
  99.       fd->fd_name[0] = '.'; fd->fd_name[1] = 0;
  100.       bp += fd->fd_namelen + sizeof (struct file_dir);
  101.       fd = (struct file_dir *) bp;
  102.       fd->fd_key = 2;
  103.       fd->fd_namelen = 2;
  104.       fd->fd_name[0] = '.'; fd->fd_name[1] = '.';
  105.       bp += fd->fd_namelen + sizeof (struct file_dir);
  106.       
  107.       /* don't include the dir-information into the file, *ix doesn't either. */
  108.       if (rc0 == -1)
  109.     for (;;)
  110.       {
  111.         /* allow for a clean abort out of a very long directory scan */
  112.         if (u.p_sig & ~omask)
  113.           {
  114.         /* if a signal is pending that was not blocked before entry to
  115.          * open(), break here and return with EINTR */
  116.         res = -1;
  117.         err = EINTR;
  118.         kfree (buf);
  119.         goto do_return;
  120.           }
  121.  
  122.         rc0 = ExNext (lock, fib);
  123.  
  124.             if (rc0 != -1) break;
  125.  
  126.             len = strlen (fib->fib_FileName);
  127.  
  128.             if ((bp + (len + 2 + sizeof (struct file_dir))) >= bend)
  129.           {
  130.             u_char *tmp;
  131.  
  132.  
  133.             tmp = krealloc (buf, buf_size + BUFINCR);
  134.             if (! tmp)
  135.           {
  136.             ix_panic ("ixemul.library: out of memory!");
  137.             res = -1;
  138.             kfree (buf);
  139.             err = ENOMEM;
  140.             goto do_return;
  141.           }
  142.  
  143.             buf_size += BUFINCR;
  144.             bp = tmp + (bp-buf);
  145.             buf = tmp; 
  146.         bend = tmp + buf_size;
  147.           }
  148.  
  149.         fd = (struct file_dir *) bp;
  150.             fd->fd_key = fib->fib_DiskKey;
  151.             fd->fd_namelen = len;
  152.             /* watch out for mc68000: don't let bp ever get odd ! */
  153.             if (fd->fd_namelen & 1) 
  154.           /* in that case zero pad the name */
  155.           fd->fd_name[fd->fd_namelen++] = 0;
  156.  
  157.         bcopy (fib->fib_FileName, fd->fd_name, len);
  158.         bp += fd->fd_namelen + sizeof (struct file_dir);
  159. #ifdef DEBUG
  160.         if (bp >= bend || & fd->fd_name[len] >= bend)
  161.           {
  162.               KPRINTF (("cd: OVERFLOW! bp = $%lx, bend = $%lx, len = $%lx, &fd->fd_name[len] = $%lx\n",
  163.               bp, bend, len, & fd->fd_name[len]));
  164.           }
  165. #endif
  166.       }
  167.       
  168.       /* fine.. fill out the memory file object */
  169.       f->f_type        = DTYPE_MEM;
  170.       f->f_mf.mf_offset = 0;
  171.       f->f_mf.mf_buffer = buf;
  172.       f->f_read        = __mread;
  173.       f->f_close    = __mclose;
  174.       f->f_ioctl    = 0;
  175.       f->f_select    = 0;
  176.       f->f_stb.st_size    = bp-buf;
  177.       /* NOTE: the rest of the stb should be ok from the previous stat() in
  178.        *       open() */
  179.     }
  180.   else
  181.     {
  182.       errno = ENOENT;
  183.       KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  184.       return -1;
  185.     }
  186.  
  187.   /* NOTE: granted, this is a bit spaghetti here.. the else above guarantees that
  188.            we won't unlock a lock we never got. So it's safe to unconditionally
  189.            unlock at the end. */
  190.  
  191. do_return:
  192.   __unlock (lock);
  193.   errno = err;
  194.   KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  195.   return res;
  196. }
  197.